package com.net.xpay.partner.controller.partner;

import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.net.common.exception.BusinessException;
import com.net.common.model.ResultData;
import com.net.common.model.ResultList;
import com.net.common.model.ResultPagedList;
import com.net.common.util.LocalDateUtil;
import com.net.common.util.StreamUtil;
import com.net.xpay.common.domain.User;
import com.net.xpay.common.domain.UserProfile;
import com.net.xpay.common.domain.UserShard;
import com.net.xpay.common.domain.partner.Partner;
import com.net.xpay.common.domain.partner.PartnerCode;
import com.net.xpay.common.domain.stat.CompanyDailyStat;
import com.net.xpay.common.enums.config.CommonSysConfigKey;
import com.net.xpay.common.helper.CommonSysConfigHelper;
import com.net.xpay.common.manager.UserManager;
import com.net.xpay.common.manager.UserProfileManager;
import com.net.xpay.common.manager.UserShardManager;
import com.net.xpay.common.manager.partner.PartnerCodeManager;
import com.net.xpay.common.manager.partner.PartnerManager;
import com.net.xpay.common.model.PartnerRegisterModel;
import com.net.xpay.common.model.PasswordModel;
import com.net.xpay.common.model.search.PartnerSearchModel;
import com.net.xpay.common.model.search.UserSearchModel;
import com.net.xpay.common.service.CompanyDailyStatService;
import com.net.xpay.core.constant.PoseidonErrorCode;
import com.net.xpay.core.domain.UserAccount;
import com.net.xpay.core.dto.AccountAmountCountDto;
import com.net.xpay.core.enums.AlipayUserStatus;
import com.net.xpay.core.enums.SafePayBookAccountSignStatus;
import com.net.xpay.core.manager.AlipayUserManager;
import com.net.xpay.core.manager.UserAccountManager;
import com.net.xpay.core.manager.safePay.SafePayBatchManager;
import com.net.xpay.core.manager.safePay.SafePayBookAccountManager;
import com.net.xpay.core.model.AlipayUserSearchModel;
import com.net.xpay.core.model.SafePayBookAccountSearchModel;
import com.net.xpay.core.utils.BeanCopierUtil;
import com.net.xpay.partner.secutiry.RequestUser;
import com.net.xpay.partner.vo.PartnerCodeVo;
import com.net.xpay.partner.vo.PartnerRegisterVo;
import com.net.xpay.partner.vo.PartnerVo;
import com.net.xpay.partner.vo.UserVo;
import com.net.shard.ShardUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.RandomUtils;
import org.mindrot.jbcrypt.BCrypt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 2019/4/1 14:45

 */
@Slf4j
@RestController
@RequestMapping("/partner")
@Api(tags = "合伙人/合伙人", description = "合伙人 合伙人 net")
public class PartnerController {
    private static final int MAX_PASS_LENGTH = 20; //最大的密码长度
    private static final int MIN_PASS_LENGTH = 6; //最小的密码长度

    @Autowired
    private UserManager userManager;

    @Autowired
    private PartnerCodeManager partnerCodeManager;

    @Autowired
    private UserAccountManager userAccountManager;

    @Autowired
    private UserShardManager userShardManager;

    @Autowired
    private CommonSysConfigHelper commonSysConfigHelper;

    @Autowired
    private PartnerManager partnerManager;

    @Autowired
    private UserProfileManager userProfileManager;

    @Autowired
    private SafePayBookAccountManager safePayBookAccountManager;

    @Autowired
    private AlipayUserManager alipayUserManager;
    @Autowired
    private CompanyDailyStatService companyDailyStatService;

    @Autowired
    private SafePayBatchManager safePayBatchManager;

    /**
     * 获取合伙人信息
     */
    @ApiOperation("获取合伙人信息")
    @GetMapping("/info")
    public ResultData<Partner> getPartnerInfo(@ApiIgnore @RequestUser Partner partner) {
        return new ResultData<>(partner);
    }

    /**
     * 推广链接
     */
    @ApiOperation("推广链接")
    @GetMapping("/referral-link")
    public ResultList<PartnerCodeVo> getPartnerReferralLink(@ApiIgnore @RequestUser Partner partner) {
        String domain = commonSysConfigHelper.getString(CommonSysConfigKey.MERCHANT_DOMAIN);
        List<PartnerCode> codes = partnerCodeManager.listByPartnerId(partner.getId());
        List<PartnerCodeVo> vos = BeanCopierUtil.batchCopy(PartnerCode.class, PartnerCodeVo.class, codes);
        vos.forEach(vo -> {
            String link = "http://" + domain + "/#/login/merchant?pma=" + vo.getPma();
            vo.setLink(link);
            vo.setName(vo.getUserTag().getDesc());
        });

        return new ResultList<>(vos);
    }

    @ApiOperation("搜索下线")
    @PostMapping("/referral-user/search")
    @ResponseBody
    public ResultPagedList<UserVo> searchMerchant(@ApiIgnore @RequestUser Partner partner, @RequestBody UserSearchModel searchModel) {
        Preconditions.checkArgument(partner.getId() != null);
        searchModel.setPartnerId(partner.getId());

        List<User> userList = userManager.search(searchModel);
        long count = userManager.searchCount(searchModel);

        List<UserVo> userVoList = BeanCopierUtil.batchCopy(User.class, UserVo.class, userList);

        if (CollectionUtils.isNotEmpty(userList)) {
            List<Long> userIdList = StreamUtil.map(userList, User::getId);
            List<UserShard> userShards = userShardManager.findByIds(userIdList);
            Map<Long, UserShard> userShardMap = StreamUtil.toMap(userShards, UserShard::getId);
            for (UserVo vo : userVoList) {
                try {
                    ShardUtil.setShardContext(userShardMap.get(vo.getId()).getShardId());
                    UserAccount userAccount = userAccountManager.findById(vo.getId());
                    vo.setMoneyLeft(userAccount.getMoneyLeft());
                    vo.setUserTagName(vo.getUserTag().getDesc());
                    if (vo.getIndustryCategory() != null) {
                        vo.setIndustryCategoryName(vo.getIndustryCategory().getDesc());
                    }
                    if (vo.getCostServiceRatio() != null) {
                        vo.setPartnerServiceRatio(vo.getServiceRatio().subtract(vo.getCostServiceRatio()));
                    }
                    if (vo.getBankCostServiceRatio() != null) {
                        vo.setPartnerBankServiceRatio(vo.getBankServiceRatio().subtract(vo.getBankCostServiceRatio()));
                    }
                    //安全发签约数
                    SafePayBookAccountSearchModel safePayBookAccountSearchModel = new SafePayBookAccountSearchModel();
                    safePayBookAccountSearchModel.setUserId(vo.getId());
                    safePayBookAccountSearchModel.setSignStatus(SafePayBookAccountSignStatus.NORMAL);
                    Long safePaySignCount = safePayBookAccountManager.searchCount(safePayBookAccountSearchModel);
                    //批量有密签约数
                    AlipayUserSearchModel alipayUserSearchModel = new AlipayUserSearchModel();
                    alipayUserSearchModel.setUserId(vo.getId());
                    alipayUserSearchModel.setStatus(AlipayUserStatus.YES);
                    alipayUserSearchModel.setIsDeleted(0);
                    Long payTransSignCount = alipayUserManager.searchCount(alipayUserSearchModel);

                    vo.setPayTransSignCount(payTransSignCount);
                    vo.setSafePaySignCount(safePaySignCount);
                    UserProfile userProfile = userProfileManager.getById(vo.getId());
                    vo.setOpenSafePayBank(userProfile.getOpenSafePayBank());
                    //累计金额
                    LocalDateTime dayTime = LocalDateUtil.getDayStart(LocalDateTime.now());
                    AccountAmountCountDto safeSuccessAmount = safePayBatchManager.sumSafeSuccessAmount(null, LocalDateUtil.getDayEnd(LocalDateTime.now().minusDays(0l)), vo.getId(),dayTime);
//                    CompanyDailyStat companyDailyStat = new CompanyDailyStat();
//                    companyDailyStat = companyDailyStatService.statCompanyDailyStatByTime(null, LocalDateUtil.getDayEnd(LocalDateTime.now().minusDays(0l)));
                    if(safeSuccessAmount!=null){
                        vo.setSumAmount(safeSuccessAmount.getSumAmount());
                        vo.setDayAmount(safeSuccessAmount.getDayAmount());
                    }else {
                        vo.setSumAmount(BigDecimal.valueOf(0l));
                        vo.setDayAmount(BigDecimal.valueOf(0l));
                    }

                }catch (Exception ex){
                    ex.printStackTrace();
                }
                finally {
                    ShardUtil.cleanShardContext();
                }
            }
        }

        return new ResultPagedList<>(userVoList, count, searchModel);
    }

    @ApiOperation("合伙人注册二级合伙人")
    @PostMapping("/register")
    @ResponseBody
    public ResultData<PartnerRegisterVo> register(@ApiIgnore @RequestUser Partner operator, @RequestBody PartnerRegisterModel registerModel) {
        throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "不支持该操作");
    }

    @ApiOperation("重置合伙人密码")
    @PostMapping("/reset-password")
    @ResponseBody
    public ResultData<String> resetPassword(@ApiIgnore @RequestUser Partner operator, Long partnerId) {
        Preconditions.checkArgument(partnerId != null);
        Partner partner = partnerManager.getById(partnerId);
        if (!Objects.equals(partner.getFatherPartnerId(), operator.getId())) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "没有权限修改");
        }

        String randomPassword = RandomStringUtils.randomAlphabetic(3).toLowerCase() + "@" + Strings.padStart("" + RandomUtils.nextInt(0, 1000000), 6, '0');
        partner.setPassword(BCrypt.hashpw(randomPassword, BCrypt.gensalt()));
        partnerManager.updateByPrimaryKeyWithVersion(partner);
        return new ResultData<>(randomPassword);
    }

    @ApiOperation("搜索下级合伙人")
    @PostMapping("/search")
    @ResponseBody
    public ResultPagedList<PartnerVo> searchPartner(@ApiIgnore @RequestUser Partner operator, @RequestBody PartnerSearchModel searchModel) {
        searchModel.setFatherPartnerId(operator.getId());
        List<Partner> records = partnerManager.search(searchModel);
        long count = partnerManager.searchCount(searchModel);

        List<PartnerVo> vos = BeanCopierUtil.batchCopy(Partner.class, PartnerVo.class, records);
        for (PartnerVo vo : vos) {
            List<PartnerCode> partnerCodes = partnerCodeManager.listByPartnerId(vo.getId());
            List<PartnerCodeVo> partnerCodeVos = BeanCopierUtil.batchCopy(PartnerCode.class, PartnerCodeVo.class, partnerCodes);
            for (PartnerCodeVo partnerCodeVo : partnerCodeVos) {
                partnerCodeVo.setName(partnerCodeVo.getUserTag().getDesc());
            }
            vo.setPartnerCodes(partnerCodeVos);
        }

        return new ResultPagedList<>(vos, count, searchModel);
    }

    @ApiOperation(value = "修改密码（登录后才能操作）")
    @PutMapping("/modify-password")
    public ResultData<Boolean> modifyPassword(@ApiIgnore @RequestUser  Partner operator, @RequestBody PasswordModel passwordModel) {
        if (operator == null) {
            throw new BusinessException(PoseidonErrorCode.NEED_LOGIN, "请先登录,登陆之后才能修改密码");
        }

        if (Strings.isNullOrEmpty(passwordModel.getOldPassword())) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "旧密码不能为空");
        }
        if (!BCrypt.checkpw(passwordModel.getOldPassword(), operator.getPassword())) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "密码不正确");
        }
        if (Strings.isNullOrEmpty(passwordModel.getPassword())) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "新密码不能为空");
        }
        if (Strings.isNullOrEmpty(passwordModel.getRepeatPassword())) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "再次输入的新密码不能为空");
        }
        if (!passwordModel.getPassword().equals(passwordModel.getRepeatPassword())) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "两次输入的新密码不一样");
        }
        if (passwordModel.getPassword().length() > MAX_PASS_LENGTH || passwordModel.getPassword().length() < MIN_PASS_LENGTH) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "密码长度必须在6到20个字符");
        }
        operator.setPassword(BCrypt.hashpw(passwordModel.getPassword(), BCrypt.gensalt()));
        partnerManager.updateByPrimaryKeyWithVersion(operator);
        return new ResultData<>(true);
    }


}
